/* JavaLog - package tracker 
 * 
 * Copyright (C) 2009  Allyson Lima, Diego Pedro, Victor Freire
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software 
 * Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this 
 * program.  If not, see <http://www.gnu.org/licenses/>.
 */
package br.edu.ufcg.ccc.javalog.controller;

import java.util.HashSet;
import java.util.Set;

import br.edu.ufcg.ccc.javalog.exceptions.BadAddressException;
import br.edu.ufcg.ccc.javalog.exceptions.FranchiseException;
import br.edu.ufcg.ccc.javalog.exceptions.HeadquartersControllerException;
import br.edu.ufcg.ccc.javalog.exceptions.HeadquartersException;
import br.edu.ufcg.ccc.javalog.model.Address;
import br.edu.ufcg.ccc.javalog.model.Franchise;
import br.edu.ufcg.ccc.javalog.model.Headquarters;
import br.edu.ufcg.ccc.javalog.model.Validator;

/**
 * Controller for Headquarter model object.
 * @author Allyson Lima, Diego Pedro, Victor Freire
 * @version 11/10/09
 */
public class HeadquartersController {
	private Headquarters headquarters;
	
	/**
	 * Constructs a controller for a headquarters model object. 
	 * @param headquarters headquarters model object to manipulate
	 */
	public HeadquartersController(Headquarters headquarters) {
		Validator.validateObject(headquarters, new IllegalArgumentException("HeadquartersController constructor received null pointer"));
		this.headquarters = headquarters;
	}
	
	/**
	 * Adds a new franchise.
	 * @throws HeadquartersControllerException Thrown when the operation fails. Always carries a message suitable for display to the end-user. 
	 */
	public void addFranchise(String name, String region, String state, String city, String street, String number, String zipcode, String district, boolean hasAirport) throws HeadquartersControllerException {
		try {
			Address address = new Address(region, state, city, district, zipcode, street, number);
			Franchise newFranchise = new Franchise(name, address, hasAirport);
			if(!headquarters.addFranchise(newFranchise)) throw new HeadquartersControllerException("Já existe uma franquia no local fornecido.");
		} 
		catch(BadAddressException e) {
			throw new HeadquartersControllerException(e.getMessage() != null ? e.getMessage() : "Erro nas informações sobre o local.");
		} 
		catch(FranchiseException e) {
			throw new HeadquartersControllerException(e.getMessage() != null ? e.getMessage() : "Falha ao criar uma nova loja.");
		} 
		catch(HeadquartersControllerException e) {
			throw e;
		}
		catch(Exception e) {
			
			handleUnknownError(e);
		}
	}
			
	/**
	 * Generates a list with the franchises that match the search arguments provided.
	 * @param name partial franchise name to compare, if it is an empty string it compares true.
	 * @param city partial city name to compare, if it is an empty string it compares true.
	 * @return collection with the franchises that mathes the search arguments. 
	 * @throws HeadquartersControllerException Thrown when the operation fails. Always carries a message suitable for display to the end-user. 
	 */
	public Set<Franchise> listFranchises(String name, String city) throws HeadquartersControllerException {
		try {
			// these strings can be null
			Validator.validateObject(name, new IllegalArgumentException("received null name string"));
			Validator.validateObject(city, new IllegalArgumentException("received null city string"));
			return headquarters.listFranchises(name, city);
		} catch(Exception e) {
			handleUnknownError(e);
		}
		return new HashSet<Franchise>(); // for robustness, return an empty set, not a null reference
	}
	
	/**
	 * Deletes a franchise.
	 * @param franchise the franchise to delete
	 * @throws HeadquartersControllerException Thrown when the operation fails. Always carries a message suitable for display to the end-user. 
	 */
	public void removeFranchise(Franchise franchise) throws HeadquartersControllerException {
		try {
			Validator.validateObject(franchise, new IllegalArgumentException("received null franchise"));
			headquarters.removeFranchise(franchise);
		} catch(HeadquartersException e) {
			throw new HeadquartersControllerException(e.getMessage() != null ? e.getMessage() : "Não foi possível remover a franquia desejada.");
		} catch(Exception e) {
			handleUnknownError(e);
		}
	}
	
	/**
	 * Handles unpredicted errors, mostly from bad code.
	 * @param e the exception caught
	 * @throws HeadquartersControllerException the processed error for the View
	 */
	private void handleUnknownError(Exception e) throws HeadquartersControllerException {
		// TODO log unexpected errors
		throw new HeadquartersControllerException(e.getMessage() != null ? e.getMessage() : "Não há informações adicionais sobre esse erro.");
	}
}



//	/**
//	 * Adds a franchise.
//	 */
//	public void addFranchise() {
//		if(!headquarters.addFranchise(ViewUtil.getFranchise())) 
//			System.out.println("Ja existe uma franquia nesse local!");
//		else
//			System.out.println("Franquia adicionada com sucesso!");
//	}
//	
//	/**
//	 * Lets the user examine a franchise.
//	 */
//	public void seeFranchise() {
//		Franchise f2 = headquarters.getFranchise(ViewUtil.getAddress());
//		if(f2 != null) { 
//			System.out.printf("Franquia encontrada: %n%n");
//			System.out.println(f2);
//		}
//		else { 
//			System.out.println("Nao existe uma franquia nesse local!");
//		}
//	}
//
//	/**
//	 * Lets the user change the airport of a franchise.
//	 */
//	public void changeFranchiseAirport() {
//		Franchise f5 = headquarters.getFranchise(ViewUtil.getAddress());
//		if(f5 != null) { 
//			System.out.printf("Franquia encontrada: %n%n");
//			System.out.println(f5);
//			f5.setHasAirport(ViewUtil.getYesOrNo("Tem aeroporto?(s/n): "));
//			System.out.println("Franquia atualizada.");
//		}
//		else { 
//			System.out.println("Nao existe uma franquia nesse local!");
//		}
//	}
//
//	/**
//	 * Lets the user change the address of a franchise.
//	 */
//	public void changeFranchiseAddress() {
//		Franchise f4 = headquarters.getFranchise(ViewUtil.getAddress());
//		if(f4 != null) { 
//			System.out.printf("Franquia encontrada: %n%n");
//			System.out.println(f4);
//			System.out.println();
//			System.out.println("Digite o novo endereco. ");
//			try {
//				f4.setAddress(ViewUtil.getAddress());
//			} catch (Exception e) {
//				assert false : "Unreachable, getAddress() always returns a valid address";
//			}
//			System.out.println("Franquia atualizada.");
//		}
//		else { 
//			System.out.println("Nao existe uma franquia nesse local!");
//		}
//	}
//
//	/**
//	 * Changes the name of the franchise.
//	 */
//	public void changeFranchiseName() {
//		Franchise f3 = headquarters.getFranchise(ViewUtil.getAddress());
//		if(f3 != null) { 
//			System.out.printf("Franquia encontrada: %n%n");
//			System.out.println(f3);
//			System.out.println();
//			f3.setName(ViewUtil.getString("Digite o novo nome: "));
//			
//		}
//		else { 
//			System.out.println("Nao existe uma franquia nesse local!");
//		}
//	}
//	
//	/**
//	 * Removes a franchise.
//	 */
//	public void removeFranchise() {
//		if(headquarters.removeFranchise(ViewUtil.getAddress()) != null)
//			System.out.println("Franquia removida com sucesso!");
//		else 
//			System.out.println("Nao existe uma franquia nesse local!");
//	}

